package json

import (
	"encoding/json"
	"fmt"
)

// json 使用

func Test() {
	fmt.Println("---------------- json ----------------")

	// 基础类型结构体
	case1()

	// 对象/结构体映射
	case2()

	// map与json互转
	case3()

	// 切片/数组处理
	case4()

	// Null值处理
	case5()
}

// 基础类型结构体
func case1() {
	fmt.Println("=== json 基础类型映射示例 ===")

	// json字符串
	jsonStr := `{
		"name": "张三",
		"product_price": 99.043,
		"product_num": 89,
		"sex": true,
		"image_array": ["image1.png","image2.png","image3.png"],
		"type_array": [1,2,3],
		"price_array": [ 68.9, 89.98, 77.09 ],
		"id":"asdf",
		"remark": null
	}`
	fmt.Println(jsonStr)

	// 反序列化
	var data1 baseicType
	// json.Unmarshal() 结构体字段首字母d大写，才能导出，小写会导致字段为空！
	err := json.Unmarshal([]byte(jsonStr), &data1)
	if err != nil {
		panic(err)
	}

	fmt.Println("将字符串json转结构体:", data1)
	fmt.Printf("Name: %s (类型: %T)\n", data1.Name, data1.Name)
	fmt.Printf("ProductPrice: %f (类型: %T)\n", data1.ProductPrice, data1.ProductPrice)
	fmt.Printf("ProductNum: %d (类型: %T)\n", data1.ProductNum, data1.ProductNum)
	fmt.Printf("Sex: %t (类型: %T)\n", data1.Sex, data1.Sex)
	fmt.Printf("ImageArray: %v (类型: %T)\n", data1.ImageArray, data1.ImageArray)
	fmt.Printf("TypeArray: %v (类型: %T)\n", data1.TypeArray, data1.TypeArray)
	fmt.Printf("PriceArray: %v (类型: %T)\n", data1.PriceArray, data1.PriceArray)
	fmt.Printf("Remark: %v (类型: %T)\n", data1.Remark, data1.Remark)

	// 序列化
	strjson, err := json.Marshal(data1)
	if err != nil {
		panic(err)
	}
	fmt.Println("将结构体转json：", string(strjson))

	// 格式化输出  - 前缀为空，缩进为两个空格
	str2json, err := json.MarshalIndent(data1, "", " ")
	fmt.Println("格式化输出，带缩进格式化json ", string(str2json))

}

// 基础类型结构体
type baseicType struct {
	// 字符串
	Name string `json:"name"`

	// 数字 - json中的数字默认解码为float64
	ProductPrice float64 `json:"product_price"`
	ProductNum   int     `json:"product_num"`

	// 布尔值
	Sex bool `json:"sex"`

	// 数组、切片
	ImageArray []string  `json:"image_array"`
	TypeArray  []int     `json:"type_array"`
	PriceArray []float64 `json:"price_array"`

	// null值  使用指针处理null值
	Remark *string `json:"remark"`
}

// 对象/结构体映射
func case2() {
	fmt.Println("=== json 对象/结构体映射 ===")

	member1 := member{
		Name:  "丽丽",
		Age:   18,
		Email: "weafs@qq.com",
		Phone: "1365345324234",
		Tag:   []int{1, 2, 3},
		Address: address{
			City: "北京市",
			Code: 10000001,
		},
	}
	fmt.Println(member1)

	// 格式化输出 - 前缀为空，缩进为两个空格
	str1json, err := json.MarshalIndent(member1, "", " ")
	if err != nil {
		panic(err)
	}
	fmt.Printf("格式化输出：%s  %T \n", string(str1json), string(str1json))

	strjson, err2 := json.Marshal(member1)
	if err2 != nil {
		panic(err)
	}
	fmt.Println("结构体转json：", string(strjson))
}

// 会员结构体
type member struct {
	Name    string `json:"name"`
	Age     int    `json:"age"`
	Email   string `json:"email"`
	Phone   string `json:"phone"`
	Tag     []int  `json:"tag"`
	Address address

	// 小写开头，不会被序列化导出
	token string
}

// 地址结构体
type address struct {
	City string `json:"city"`
	Code int    `json:"code"`
}

// map与json互转
func case3() {
	fmt.Println("=== map与json互转 ===")

	// json字符串 转 map
	jsonStr := `{"name":"张三","age":25,"hobbies":["读书","编程"],"address":{"city":"北京","street":"朝阳区"},"scores":[95,87,92]}`

	var map1 map[string]interface{}               //定义map
	err := json.Unmarshal([]byte(jsonStr), &map1) //将json字符串转map
	if err != nil {
		panic(err)
	}

	fmt.Println("json转map结果：", map1)
	for k, v := range map1 {
		fmt.Printf("key:%s, value:%v (数据类型：%T)\n", k, v, v)
	}
	fmt.Println("map1获取 name值", map1["name"])
	fmt.Println("map1获取 age值", map1["age"])
	fmt.Println("map1获取 hobbies值", map1["hobbies"].([]interface{}))
	fmt.Println("map1获取 address值", map1["address"].(map[string]interface{}))

	// map 转 json
	map2 := map[string]interface{}{
		"id":   101,
		"name": "丽丽",
		"city": map[string]interface{}{
			"age":     28,
			"name":    "广东",
			"married": false,
		},
		"skills": []string{"go", "java"},
	}

	fmt.Println("定义的map2：", map2)
	strjson, err := json.Marshal(map2)
	if err != nil {
		panic(err)
	}
	fmt.Println("map 转json :", string(strjson))

}

// 切片/数组处理
func case4() {
	fmt.Println("=== 切片/数组处理 ===")

	bookArr := []book1{
		{ID: 1, Name: "Mysql8.0精通", Price: 88.90},
		{ID: 2, Name: "Mysql8.0入门到放弃", Price: 250.09},
		{ID: 3, Name: "Mysql8.0高级应用", Price: 250.00},
	}
	fmt.Println("切片书籍：", bookArr)

	// 切片转json
	strjson, err := json.Marshal(bookArr)
	if err != nil {
		panic(err)
	}
	fmt.Println("切片转json: ", string(strjson))

	// json 转 切片
	jsonstr := `[{"id":1,"name":"Mysql8.0精通","price":88.9},{"id":2,"name":"Mysql8.0入门到放弃","price":250.09},{"id":3,"name":"Mysql8.0高级应用","price":250}]`

	var bookArr2 []book1
	err2 := json.Unmarshal([]byte(jsonstr), &bookArr2)
	if err2 != nil {
		panic(err2)
	}
	fmt.Println("json 转切片", bookArr2)
	for i, v := range bookArr2 {
		fmt.Printf("bookArr2[%d]=%v\n", i, v)
	}

	// json 转基础类型切片
	str1 := `[1,2,34]`
	var ageArr []int
	err3 := json.Unmarshal([]byte(str1), &ageArr)
	if err3 != nil {
		panic(err3)
	}
	fmt.Println("json 转基础类型切片：", ageArr)

	str2 := `["mi","vivo","oppo"]`
	var brandArr []string
	json.Unmarshal([]byte(str2), &brandArr)
	fmt.Println("json 转基础类型切片：", brandArr)

}

// 书籍 结构体
type book1 struct {
	ID    int     `json:"id"`
	Name  string  `json:"name"`
	Price float64 `json:"price"`
}

// Null值处理
func case5() {
	fmt.Println(" === Null值处理 ===")

	// JSON包含null值
	jsonStr := `{
		"name": "张三",
		"age": null,
		"email": "zhangsan@example.com"
	}`

	var t1 nullTable
	json.Unmarshal([]byte(jsonStr), &t1)

	fmt.Println("Null值处理结果:", t1)
	fmt.Println(t1.Name, " ", *t1.Name)
	if t1.Name != nil {
		fmt.Printf("Name: %s\n", *t1.Name)
	} else {
		fmt.Println("Name: null")
	}

	var t2 nullTable = nullTable{
		Name:  stringPtr("lisi"),
		Age:   nil,
		Email: stringPtr("zhangsan@example.com"),
	}
	fmt.Println(t2)
	strjson, err := json.Marshal(t1)
	if err != nil {
		panic(err)
	}
	fmt.Println(string(strjson))

}

type nullTable struct {
	Name      *string `json:"name"`
	Age       *int    `json:"age"`
	Email     *string `json:"email"`
	Optaional *string `json:"optaional,omitempty"`
}

// 辅助函数：创建字符串指针
func stringPtr(s string) *string {
	return &s
}
